//
// Created by Gao Shihao on 2023/8/31.
//

#ifndef PLC2LLVM_METHODTYPE_H
#define PLC2LLVM_METHODTYPE_H
#include "plc2llvm/TypeSystem/UserDefType.h"

namespace plcst {
    class MethodType: public UserDefType {
    public:
        using TypeUptr = std::unique_ptr<Type>;


        explicit MethodType(std::string&& name): UserDefType(std::move(name)) {}

        explicit MethodType(MethodType* another) : UserDefType(another) { }

        void setReturnType(TypeUptr rt);

        [[nodiscard]] TypeKind getTypeKind() const override;

        virtual ConvertionSignal canConvertTo(std::shared_ptr<Type> dest) override{
            if(this->getTypeKind() == dest->getTypeKind()){ //类型相同
                return ConvertionSignal::IMPLICIT_CONVERSION;
            }
            return ConvertionSignal::ERROR_CONVERSION; // TODO
        }

        virtual TypeMsg typeSynthesisForBinaryOperator(ExpressionOperator op, std::shared_ptr<Type> another) override{
            return {nullptr, 2}; // TODO
        }

        virtual TypeMsg typeSynthesisForUnaryOperator(ExpressionOperator op) override {
            return {nullptr, 2};// TODO
        }

        virtual std::shared_ptr<Type> clone() override {
            return std::make_shared<MethodType>(this);
        }

    private:
        TypeUptr returnType;
        std::vector<TypeUptr> input;
        std::vector<TypeUptr> output;
        std::vector<TypeUptr> inOutput;
    };

    void MethodType::setReturnType(MethodType::TypeUptr rt) {
        returnType = std::move(rt);
    }

    TypeKind MethodType::getTypeKind() const {
        return TypeKind::METHOD;
    }

}
#endif //PLC2LLVM_METHODTYPE_H
